package com.izhengyin.dddmessage.domain.aggregate.message.specification;

import com.izhengyin.dddmessage.domain.aggregate.message.entity.Message;
import com.izhengyin.dddmessage.domain.shared.enums.MessageStatus;
import com.izhengyin.dddmessage.domain.shared.specification.AbstractSpecification;
import com.izhengyin.dddmessage.domain.shared.specification.InteractiveSpecification;
import com.izhengyin.dddmessage.domain.shared.specification.Specification;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

/**
 * 消息状态业务逻辑
 * @author zhengyin
 * Created on 2021/7/13
 */
@Component
public class MessageStatusSpecification extends AbstractSpecification<Message> implements InteractiveSpecification<Message, MessageStatus> {
    private final List<InteractiveSpecification<Message,MessageStatus>> specifications;
    public MessageStatusSpecification(StopWordSpecification stopWordSpecification,BlockedSpecification blockedSpecification,SafetySpecification safetySpecification){
        //组合规约
        this.specifications = Collections.unmodifiableList(Arrays.asList(stopWordSpecification,blockedSpecification,safetySpecification));
    }
    @Override
    public void notSatisfiedHandleBy(Message message, Consumer<MessageStatus> handle) {
        AtomicBoolean processed = new AtomicBoolean(false);
        for (InteractiveSpecification<Message,MessageStatus> specification : specifications){
            if(processed.get()){
                break;
            }
            specification.notSatisfiedHandleBy(message,messageStatus -> {
                handle.accept(messageStatus);
                processed.compareAndSet(false,true);
            });
        }
    }
    @Override
    public boolean isSatisfiedBy(Message message) {
        for (Specification<Message> specification : specifications){
            if(!specification.isSatisfiedBy(message)){
                return false;
            }
        }
        return true;
    }
}
